package com.example.gateway.designPattern.proxy;

import com.example.gateway.designPattern.proxy.cglb.CglibProxy;
import com.example.gateway.designPattern.proxy.dtdl.DynamicProxyHandler;

import java.lang.reflect.Proxy;

/**
 * @ClassName: Client
 * @Description:
 * @Author: YourName
 * @Date: 2024/12/31
 */

public class Client {
    public static void main(String[] args) {
        /*
        * 静态代理:
        *  优点：可以做到在符合开闭原则的情况下对目标对象进行功能扩展。
        *  缺点：因为代理对象需要与目标对象实现一样的接口，所以会有很多代理类，类太多。同时，一旦接口增加方法，目标对象与代理对象都要维护。
        */

        System.out.println("-----------static Proxy-------------");

        BuyHouseImpl buyHouse = new BuyHouseImpl();

        BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);
        buyHouseProxy.buyHouse();

        /*
         * 动态代理:
         *   优点：动态代理对象不需要实现接口，但是需要传入目标对象，所以需要目标对象满足反射要求。
         *   缺点：动态代理是通过反射机制实现，代理对象调用目标对象的方法时，会多一层反射，所以效率较低。
         *
         *  但是还是有一点点小小的遗憾之处，那就是它始终无法摆脱仅支持interface代理的桎梏（我们要使用被代理的对象的接口），
         *  因为它的设计注定了这个遗憾。
         *
         *   new Class[]{BuyHouse.class}, // 代理对象与目标对象实现相同接口
         */

        System.out.println("-----------JDK Proxy-------------");
        BuyHouse proxyBuyHouse = (BuyHouse) Proxy.newProxyInstance(
                BuyHouse.class.getClassLoader(), // 代理对象与目标对象使用相同的类加载器
                new Class[]{BuyHouse.class}, // 代理对象与目标对象实现相同接口
                new DynamicProxyHandler(buyHouse) // 通过InvocationHandler来处理
        );
        proxyBuyHouse.buyHouse();



        /*
         * CGLB代理:
         *
         * 动态生成一个要代理类的子类，子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用，顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
         *
         *  优点：CGLib动态代理的生成是利用ASM（一个java字节码操作框架）在内存中动态构建子类，代理类的生成速度很快，生成代理类的过程是利用字节码处理框架ASM，通过字节码转换生成目标类的子类，CGLib动态代理是目标类没有实现接口的情况下，才采用的方法。
         *  缺点：CGLib动态代理是通过继承目标类来实现的，所以目标类不能使用final修饰。
         *
         *
         *  ASM 是一个Java字节码操控框架，它能被用来动态生成类或者增强既有类的功能。ASM可以直接产生二进制的class文件，也可以在类被加载到Java虚拟机之前动态改变类行为。
         *  https://blog.csdn.net/qq_43456605/article/details/135100001
         *
         *
         */
        System.out.println("-----------CGLB Proxy-------------");
        CglibProxy cglibProxy = new CglibProxy();
        BuyHouse cllbBuyHouseProxy = (BuyHouse)cglibProxy.getInstance(buyHouse);
        cllbBuyHouseProxy.buyHouse();


    }
}
